﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace IPC.Communication.Core
{
    public sealed class SimpleHybirdLock : IDisposable
    {
	    private bool disposedValue = false;

	    private int m_waiters = 0;

	    private readonly Lazy<AutoResetEvent> m_waiterLock = new Lazy<AutoResetEvent>(() => new AutoResetEvent(initialState: false));

	    private static long simpleHybirdLockCount;

	    private static long simpleHybirdLockWaitCount;

	    public bool IsWaitting 
        {
            get
            {
                return m_waiters != 0;
            }
        }

	    public static long SimpleHybirdLockCount
        {
            get
            {
                return simpleHybirdLockCount;
            }
            set
            {
                simpleHybirdLockCount = value;
            }
        }

        public static long SimpleHybirdLockWaitCount
        {
            get
            {
                return simpleHybirdLockWaitCount;
            }
            set
            {
                simpleHybirdLockWaitCount = value;
            }
        }

	    private void Dispose(bool disposing)
	    {
		    if (!disposedValue)
		    {
			    if (disposing)
			    {
			    }
			    m_waiterLock.Value.Close();
			    disposedValue = true;
		    }
	    }

	    public void Dispose()
	    {
		    Dispose(disposing: true);
	    }

	    public void Enter()
	    {
		    Interlocked.Increment(ref simpleHybirdLockCount);
		    if (Interlocked.Increment(ref m_waiters) != 1)
		    {
			    Interlocked.Increment(ref simpleHybirdLockWaitCount);
			    m_waiterLock.Value.WaitOne();
		    }
	    }

	    public void Leave()
	    {
		    Interlocked.Decrement(ref simpleHybirdLockCount);
		    if (Interlocked.Decrement(ref m_waiters) != 0)
		    {
			    Interlocked.Decrement(ref simpleHybirdLockWaitCount);
			    m_waiterLock.Value.Set();
		    }
	    }
    }
}
